package edu.uw.cs.cse461.sp12.snet;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Random;

import edu.uw.cs.cse461.sp12.OS.OS;
import edu.uw.cs.cse461.sp12.OS.SNetControl;
import edu.uw.cs.cse461.sp12.SNetDB.SNetDB461.Photo;
import edu.uw.cs.cse461.sp12.util.IPFinder;
import edu.uw.cs.cse461.sp12.util.BitmapLoader;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.Contacts.Extensions;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class SNetMain extends Activity {
	private static final String TAG = "SNetMain";
	
	private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 111;
	private static final int CHOOSE_PICTURE_ACTIVITY_REQUEST_CODE = 222;
	private static final int SNET_UPDATE_ACTIVITY_REQUEST_CODE = 333;
	
	private static final int DISPLAY_IMAGE_WIDTH = 140;
	private static final int DISPLAY_IMAGE_HEIGHT = 140;
	
    public static Context APP_CONTEXT = null;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        startServer();
        
        Log.d(TAG, "Gallery Dir: " + OS.galleryDir().getAbsolutePath());
        
        TextView domainText = (TextView) findViewById(R.id.domain_text);
        domainText.setText(String.format(getString(R.string.domain_format), OS.hostname()));
        
        Button takePictureButton = (Button) findViewById(R.id.take_picture_button);
        takePictureButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				takePicture();
			}
        });
        Button choosePictureButton = (Button) findViewById(R.id.choose_picture_button);
        choosePictureButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				choosePicture();
			}
        });
        Button updateButton = (Button) findViewById(R.id.update_button);
        updateButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				update();
			}
        });

    	updateActivityView();
    }
    
    @Override
    protected void onResume() {
    	super.onResume();
    	updateActivityView();
    }
    
    private void takePicture() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }
    
    private void choosePicture() {
    	Uri galleryUri = Uri.parse("file://" + Environment.getExternalStorageDirectory());
    	Log.d(TAG, "Updating gallery URI: " + galleryUri.toString());
		
		// Try to update gallery viewer
		sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, galleryUri));
        
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
		startActivityForResult(Intent.createChooser(intent, "Select Chosen Picture"), CHOOSE_PICTURE_ACTIVITY_REQUEST_CODE);
    	
    	updateActivityView();
    }
    
    private void update() {
		Intent intent = new Intent(SNetMain.this, SNetUpdate.class);
		startActivityForResult(intent, SNET_UPDATE_ACTIVITY_REQUEST_CODE);
    	
    	updateActivityView();
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	try {
	    	if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
	    		// Came back from taking a photo
	    		try {
	    			// Get bitmap data
	        		Bitmap photoBmp = (Bitmap) data.getExtras().get("data");
	        		
	        		
	        		
	        		// Save to file
	        		Random rand = new Random();
		    		File takenPhotoFile = new File(OS.galleryDir(), "my_photo_" + SNetControl.getGeneration() + ".jpg");
		    		FileOutputStream out = new FileOutputStream(takenPhotoFile);
		    		photoBmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
		    		out.close();
		    		
		    		// Save it as myPicture in DB
		    		SNetControl.setMyPhoto(takenPhotoFile);
	    		} catch (Exception e) {
	    			handleError(e);
	    		}
	    		
	    	} else if (requestCode == CHOOSE_PICTURE_ACTIVITY_REQUEST_CODE) {
	    		// Came back from choosing a photo
	    		
	    		if (data != null) {
		    		Uri selectedImage = data.getData();
		    		
		    		Log.d(TAG, "Uri for selectedImage: " + selectedImage.toString());

		    		String[] projection = { MediaStore.Images.Media.DATA };
	    		    Cursor cursor = getContentResolver().query(selectedImage, projection, null, null, null);
	    		    
	    		    if (cursor != null) {
		    		    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		    		    cursor.moveToFirst();
		    		    String filePath = cursor.getString(column_index);
			    		cursor.close();
		    		    
			    		Log.d(TAG, "You chose file path: " + filePath);
			    		
			    		File chosenPhotoFile = new File(filePath);
			    		if (!chosenPhotoFile.exists()) {
			    			throw new RuntimeException("Chosen photo does not exist!");
			    		}
			    		
			    		// Figure out the hash of the photo
			    		Photo chosenPhoto = new Photo(chosenPhotoFile);
			    		
			    		// Set it up in the database
			    		SNetControl.setChosenPhoto(chosenPhoto.hash());
	    		    } else {
	    		    	throw new RuntimeException("query returned null Cursor");
	    		    }
	    		} else {
	    			Log.d(TAG, "Choose Picture returned null data");
	    		}
	    	} else if (requestCode == SNET_UPDATE_ACTIVITY_REQUEST_CODE) {
	    		// Came back from updating SNet
	    	}
	    	updateActivityView();
    	} catch (Exception e) {
    		handleError(e);
    	}
    }
    
    private void updateActivityView() {
    	Log.d(TAG, "Updating Activity View");
    	
        TextView ipPortText = (TextView) findViewById(R.id.ip_port_text);
        ipPortText.setText(String.format(getString(R.string.ip_port_format), 
        								IPFinder.getIpAddress(), OS.serverPort()));
        
        try {
        	TextView myPhotoHashText = (TextView) findViewById(R.id.my_photo_hash);
            ImageView myPhotoImage = (ImageView) findViewById(R.id.my_photo_image);
            File myPhotoFile = SNetControl.getMyPhoto();
            if (myPhotoFile != null) {
            	// We have a photo
            	
                Bitmap bitmap = BitmapLoader.loadBitmap(myPhotoFile.getAbsolutePath(), 
                							DISPLAY_IMAGE_WIDTH, DISPLAY_IMAGE_HEIGHT);
                myPhotoImage.setImageBitmap(bitmap);
                
                Photo photoHash = new Photo(myPhotoFile);
                myPhotoHashText.setText(String.format(getString(R.string.hash_format), photoHash.hash()));
                
            	myPhotoImage.setVisibility(View.VISIBLE);
                myPhotoHashText.setVisibility(View.VISIBLE);
            } else {
            	myPhotoImage.setVisibility(View.INVISIBLE);
                myPhotoHashText.setVisibility(View.INVISIBLE);
            }
        } catch (Exception e) {
        	handleError(e);
        }
        try {
        	TextView chosenPhotoHashText = (TextView) findViewById(R.id.chosen_photo_hash);
            ImageView chosenPhotoImage = (ImageView) findViewById(R.id.chosen_photo_image);
            File chosenPhotoFile = SNetControl.getChosenPhoto();
            if (chosenPhotoFile != null) {
            	// We have a photo
            	chosenPhotoImage.setImageBitmap(BitmapLoader.loadBitmap(chosenPhotoFile.getAbsolutePath(), 
            									DISPLAY_IMAGE_WIDTH, DISPLAY_IMAGE_HEIGHT));

                Photo photoHash = new Photo(chosenPhotoFile);
                chosenPhotoHashText.setText(String.format(getString(R.string.hash_format), photoHash.hash()));
                
            	chosenPhotoImage.setVisibility(View.VISIBLE);
            	chosenPhotoHashText.setVisibility(View.VISIBLE);
            } else {
            	chosenPhotoImage.setVisibility(View.INVISIBLE);
            	chosenPhotoHashText.setVisibility(View.INVISIBLE);
            }
        } catch (Exception e) {
        	handleError(e);
        }
    }
    
	private void handleError(Exception e) {
		Log.d(TAG, "Encountered Exception: " + e.getMessage());
		for (StackTraceElement ste : e.getStackTrace()) {
			Log.d(TAG, "\t" + ste.toString());
		}
		
    	Toast toast = Toast.makeText(getApplicationContext(), "ERROR: " + e.getMessage(), Toast.LENGTH_SHORT);
    	toast.show();
	}
	
    private void startServer() {
    	try {
            APP_CONTEXT = this.getApplicationContext();
            
    		String configFilename = "android.config.ini";
    		Properties config = new Properties();
    		config.load(getAssets().open(configFilename));
    		
    		// boot the OS
    		OS.boot(config, Environment.getExternalStorageDirectory());
    		// Load relevant services
    		OS.startServices(OS.rpcServiceClasses);
    		OS.startServices(OS.ddnsServiceClasses);
    		OS.startServices(OS.httpdServiceClasses);
    		OS.startServices(OS.snetServiceClasses);
    		SNetControl.setup();
    	} catch (Exception e) {
    		Log.e(TAG, "Error while starting server: " + e.getMessage(), e);
    	}
    }
}